/** =====================================================
 * Copyright © hk. 2022-2025. All rights reserved.
 * File name  : 04_queue_key.c
 * Author     : 上上签
 * Date       : 2023-12-06
 * Version    : 
 * Description: 
 * ======================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <aos/kernel.h>
#include "aos/init.h"
#include "board.h"
#include <k_api.h>
#include "aos/hal/gpio.h"
#include "ulog/ulog.h"

#define RED_LED   0 // PA14
#define GRE_LED   1 // PA15

#define KEY1_PORT 8 // PA5
#define KEY2_PORT 2 // PA22
#define KEY3_PORT 4 // PA23

#define TASK_KEY_NAME   "task_key"
#define TASK_QUEUE_NAME "task_queue"
#define MOUDLE_NAME     "key_led_queue"

#define MAX_QUEUE_LEN   10
static uint32_t key_queue_arr[MAX_QUEUE_LEN] = {0};
static aos_queue_t key_queue;
const uint32_t key_short = 1;
const uint32_t key_long  = 2;

aos_task_t  task1_handle;
aos_task_t  task2_handle;

gpio_dev_t  led_gpio_dev[2] = {0}; 
gpio_dev_t  key_gpio_dev;
uint32_t    key_value;

void task_key_entry(void *arg)
{
    int ret = 0;
    const char * task_name;
    long long cpu_ms_value1, cpu_ms_value2;
    task_name = aos_task_name();
    
    while(1) 
    {
        hal_gpio_input_get(&key_gpio_dev, &key_value);
        if(!key_value)
        {
           //延时去抖动
           aos_msleep(10);
           //再次判断是否按下
           hal_gpio_input_get(&key_gpio_dev, &key_value);
           if(!key_value)
           {
                //获取按下时cpu的当前时间
                cpu_ms_value1 = aos_now_ms();
                //等待按键松开
                do{
                    
                    hal_gpio_input_get(&key_gpio_dev, &key_value);
                    aos_msleep(10);
                }while(!key_value);
                //获取松开时cpu的当前时间
                cpu_ms_value2 = aos_now_ms();
                LOGE(MOUDLE_NAME, "[%s]key down --> up time is %ld ms!", task_name, cpu_ms_value2 - cpu_ms_value1);
                //是否大于2S
                if ((cpu_ms_value2 - cpu_ms_value1) > 2000)
                {
                    ret = aos_queue_send(&key_queue, (void *)&key_long, sizeof(key_long));
                    if (ret != 0)
                    {
                        LOGE(MOUDLE_NAME, "queue send key_long error");
                    }
                }
                else
                {
                    ret = aos_queue_send(&key_queue, (void *)&key_short, sizeof(key_short));
                    if (ret != 0)
                    {
                        LOGE(MOUDLE_NAME, "queue send key_short error");
                    }
                }
           }
        }
        //10ms 读取一次按键状态
        aos_msleep(10);
    }

}

void task_queue_entry(void *arg)
{
    int ret = 0;
    uint32_t message[MAX_QUEUE_LEN] = {0};
    int size = 0;
    const char * task_name;
    int index = 0;
    task_name = aos_task_name();
    while (1)
    {
        index = 0;
        ret = aos_queue_recv(&key_queue, AOS_WAIT_FOREVER, &message[index], &size);
        if (ret == 0)
        {
            //短击
            if(message[index] == key_short)
            {
                LOGI(MOUDLE_NAME, "[%s]key is short!", task_name);
                index++;
                ret = aos_queue_recv(&key_queue, 300, &message[index], &size);
                if(ret == 0)
                {
                    if(message[index] == key_short)
                    {
                       LOGI(MOUDLE_NAME, "[%s]key is double!", task_name); 
                    }
                }
            }
            //长按
            else if(message[index] == key_long)
            {
                LOGI(MOUDLE_NAME, "[%s]key is long!", task_name);
            } 
        }
    }
}
int led_init(void)
{
    //由于PA14时rtl8710的jtag接口，我要使用GPIO功能，必须先关闭jtag借口
    sys_jtag_off();
    led_gpio_dev[0].port = RED_LED;
    led_gpio_dev[0].config = OUTPUT_PUSH_PULL;
    led_gpio_dev[0].priv = NULL;
    //gpio PA14初始化
    hal_gpio_init(&led_gpio_dev[0]);

    led_gpio_dev[1].port = GRE_LED;
    led_gpio_dev[1].config = OUTPUT_PUSH_PULL;
    led_gpio_dev[1].priv = NULL;
    //gpio PA14初始化
    hal_gpio_init(&led_gpio_dev[1]);

    return 0;
}

int key_init(void)
{
    key_gpio_dev.port = KEY1_PORT;
    //根据原理图分析配置位输入上拉模式
    key_gpio_dev.config = INPUT_PULL_UP;
    key_gpio_dev.priv = NULL;
    //key 初始化
    hal_gpio_init(&key_gpio_dev);

    return 0;
}

int application_start(int argc, char *argv[])
{
    int ret = 0;
    int index = 0;

    led_init();
    key_init();
    aos_set_log_level(AOS_LL_INFO);

	//创建任务
    ret = aos_task_new(TASK_KEY_NAME, task_key_entry, NULL, 8*128);
    if(ret != 0)
    {
        LOGE(MOUDLE_NAME, "task key new error");
    }
    ret = aos_task_new(TASK_QUEUE_NAME, task_queue_entry, NULL, 8*128);
    if(ret != 0)
    {
        LOGE(MOUDLE_NAME, "task queue new error");
    }

    //创建消息队列
    ret = aos_queue_new(&key_queue, key_queue_arr, sizeof(key_queue_arr), sizeof(uint32_t));
    if(ret != 0)
    {
        LOGE(MOUDLE_NAME, "queue new error");
    }

    while(1)
    {
        aos_msleep(1000);
        hal_gpio_output_toggle(&led_gpio_dev[1]);
    }
  
}
